/*
 * Copyright (C) 2010 ST-Ericsson AS
 * Author: Erwan Bracq / erwan.bracq@stericsson.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 */

#ifndef MID_STATEMACHINE
#define MID_STATEMACHINE

// C standard headers
#include <stdint.h>

// Posix headers
#include <unistd.h>

// Library headers
#include <libconfig.h>
#include <apr_pools.h>
#include <apr_thread_mutex.h>
#include <apr_thread_proc.h>

// MID headers
#include "mid_fw_upgrade.h"
#include "mid_conf.h"
#include "crash_dump.h"
#include "mid_mfa.h"

struct mid_power;

typedef enum MID_State_e {
	STATE_OFF,
	STATE_BOOT,
	STATE_MODINF_UP,
	STATE_ON,
	STATE_DUMP,
	STATE_SHUTDOWN,
	STATE_FLASHING,
} MID_State_t;

typedef enum MID_Event_e {
	MID_IPC_RBT_EVT=                 0,
	MID_GPIO_RST2_EVT=               1,
	MID_GPIO_PRST_EVT=               2,
	MID_MODEM_HALT_EVT=              3,
	MID_MODEM_START_EVT=             4,
	MID_SIG_KILL_EVT=                5,
	MID_LONG_OPS_EVT=                6,
	MID_CFRDY_EVT=                   7,
	MID_HIGH_TEMPERATURE_EVT=        8,
	MID_LOW_BATTERY_EVT=             9,
	MID_AT_CFUN0_EVT=               10,
	MID_AT_CFUN100_EVT=             11,
	MID_IPC_FW_UPGR_IMG_XFER_EVT=   12,
	MID_IPC_FW_UPGR_FLASH_EVT=      13,
	MID_IPC_FW_UPGR_STATUS_EVT=     14,
	MID_FW_XFER_OPS_EVT=            15,
	MID_FW_XFER_PROGRESS_EVT=       16,
	MID_TIMEOUT_EVT=                17,
	MID_FLASH_START_EVT=            18,
	MID_FLASH_END_EVT=              19,
	MID_LAST_EVT=                   20, /* End marker */
} MID_Event_t;

struct mid {
	/* Mutex */
	apr_thread_mutex_t* mutex;
	apr_pool_t* pool;
	/* Internal state machine */
	uint32_t long_ops_result;
	MID_State_t state;
	MID_Event_t event;
	MID_Event_t cur_event;
	/* Configuration */
	struct mid_config* config;
	/* GPIO settings */
	int gpio_initialized;
	struct mid_gpio_context* gpios;
	/* CFG settings */
	FILE *cfg_fd;
	/* PID settings */
	FILE *pid_fd;
	/* MID specific */
	/* 0 = OnSwA, power on(or off) by putting GPIO high for a few secconds */
	/* 1 = OnSwC, power on by putting GPiO high as long the modem shall be on */
	int power_on_release;
	int prep_for_shutdown;
	char *at_cfun_resp;
	char *at_cfun0_resp;
	char *at_cfun100_resp;
	char* modem_build_string;
	/* FD structures */
	int at_chnl_fd;
	/* Long operation threads */
	apr_thread_t* mid_flboot_td;
	apr_thread_t* mid_rfmsleep_td;
	apr_thread_t* mid_delay_powon_td;
	apr_thread_t* mid_crashdump_td;
	apr_thread_t* mid_fw_upgrade_td;
	int kill_threads;

	/* Firmware upgrade */
    	void * fw_upgr_img_xfer_reply_msg;
	void * fw_upgr_flash_reply_msg;
	void * fw_upgr_status_reply_msg;
	int fw_xfer_result;
	char * fw_upgr_status_string;
	unsigned char fw_upgr_xfer_progress;
	int fw_upgr_last_error;

	/* Utils path */
	int flash_retry_left;
	int flash_failed;
	int boot_retry_left;
	int boot_failed;
	int shutdown_retry_left;
	int modem_warm_start;

	/* Due to missing GPIO support(GPIO_PWRRSTIN) we need in some */
	/* usecases(e.g. ITP which turn off the modem without MIDs knowledge */
	/* to track the modem state. Should be removed/dissabled when having GPIO_PWRRSTIN */
	int modem_is_on;

	/* Added new field */
	int ipc_reboot_received;

	/* Modem Library DSO handle */
	void *dl_handle;
	/* Modem Library functions */
	char * (*moli_fw_upgr_get_error_str)(struct mid *mid_info, int error_code);
	void * (*moli_boot)(apr_thread_t* thread, void *arg);
	int (*moli_configure_security_data)(struct mid *mid_info);
	int (*moli_get_crash_dump)(struct mid *midinfo, struct mid_dev *dev, const char* dump_directory, const char* dump_directory_header, const char* dump_filename, const char* dump_filename_header, int dump_timestamp, crash_dump_report_t report_type, int max_dump_files);
	int (*moli_fw_upgrade_flash)();
	void (*moli_fw_upgrade_init)(int *error_code_p);
	int (*moli_fw_upgrade_status)(char **status);
	int (*moli_fw_upgrade_img_xfer)(struct mid *mid_info);
	char * (*moli_fw_upgr_modem_error_code_str)();
	char * (*moli_fw_upgrade_get_error_str)(struct mid *mid_info, int error_code);

	struct mid_power* mid_power;

	struct mid_mfa* mfa;

#ifdef PERF_MEASUREMENT
	/* Performance issue */
	struct timespec midStarted;           /*Time when modem mid is started                   */
	struct timespec modemBootStarted;     /*Time when starting to prepare modem for booting  */
	struct timespec modemImagesStarted;   /*Time when starting to transfer modem images(FLB) */
	struct timespec modemImagesFinished;  /*Time when modem images is transferred            */
	struct timespec modemRST2;            /*Time when receiving RST2                         */
	struct timespec modemCFRDY;           /*Time when receiving CFRDY                        */
#endif
};

void mid_statemachine_process_all_events(struct mid* mid_info, time_t* time_entered_state);
int mid_statemachine_get_current_timeout(struct mid* mid_info);
void shutdown_modem(struct mid* mid_info);
int state_all_evt_sig_kill(struct mid* mid_info);
const char* mid_statemachine_get_name_of_current_state(struct mid* mid_info);
bool mid_statemachine_get_event_by_name(const char* name, MID_Event_t* event);

#if defined(MOTOROLA_FEATURE)
void mid_statemachine_log_panic_apr(const char *panic_msg, const char *panic_file);
#endif

#endif
